# @Time : 2020/6/28 9:19
# @Author : Fioman 
# @Phone : 13149920693

from collections import namedtuple

Customer = namedtuple("Customer", "name fidelity")


class LineItem(object):
    def __init__(self, product, quantity, price):
        self.product = product
        self.quantity = quantity
        self.price = price

    def total(self):
        return self.price * self.quantity


class Order(object):  # 上下文
    def __init__(self, customer, cart, promotion=None):
        self.customer = customer
        self.cart = list(cart)
        self.promotion = promotion

    def total(self):
        if not hasattr(self, '__total'):
            self.__total = sum(item.total() for item in self.cart)
        return self.__total

    def due(self):
        if self.promotion is None:
            discount = 0
        else:
            discount = self.promotion(self)

        return self.total() - discount

    def __repr__(self):
        fmt = '<Order total: {:.2f} due: {:2f}>'
        return fmt.format(self.total(), self.due())


def fidelity_promo(order):
    """为积分为1000或者以上的顾客提供5%折扣"""
    return order.total() * .05 if order.customer.fidelity >= 1000 else 0


def bulk_item_promo(order):
    """单个商品为20或以上时提供10%折扣"""
    discount = 0
    for item in order.cart:
        if item.quantity >= 20:
            discount += item.total() * .1

    return discount


def large_order_promo(order):
    """订单中的不同商品达到10个或以上时提供7%折扣"""
    distinct_items = {item.product for item in order.cart}
    if len(distinct_items) >= 10:
        return order.total() * .07
    return 0


if __name__ == '__main__':
    joe = Customer("John Doe", 0)
    ann = Customer("Ann Simith", 1100)
    cart = [LineItem("banana", 4, .5),
            LineItem("apple", 10, 1.5),
            LineItem("watermellon", 5, 5.6)]

    order1 = Order(joe, cart, fidelity_promo)
    print("order1 = {}".format(order1))

    order2 = Order(ann, cart, fidelity_promo)
    print("order2 = {}".format(order2))

    banana_cart = [LineItem("banana", 30, .5),
                   LineItem("apple", 10, 1.5)]

    order3 = Order(joe, banana_cart, bulk_item_promo)
    print("order3 = {}".format(order3))

    long_order = [LineItem(str(item_code), 1, 1.0) for item_code in range(10)]

    order4 = Order(joe,cart,large_order_promo)
    print("order4 = {}".format(order4))

    order5 = Order(joe,long_order,large_order_promo)
    print("order5 = {}".format(order5))